#ifndef _THREAD_BASE_HH_H
#define _THREAD_BASE_HH_H

namespace GSTrader
{
	namespace TradeBase
	{
		class xrecursive_mutex
		{
		public:
			xrecursive_mutex() : recursion_count(0){}
			~xrecursive_mutex(){}

			//    serious warning: you must only call this func in the thread already hold permission of this mutex!
			int get_recursion_count()
			{
				return recursion_count;
			}

			void lock()
			{
				mutex.lock();
				++recursion_count;
			}

			//    serious warning: you must only call this func in the thread already hold permission of this mutex!
			void unlock()
			{
				--recursion_count;
				mutex.unlock();
			}

			//    lock of RAII style
			class scoped_lock
			{
			public:
				scoped_lock(xrecursive_mutex& mtx_)
					: mtx(mtx_)
				{
					mtx.lock();
				}

				~scoped_lock()
				{
					mtx.unlock();
				}

			private:
				xrecursive_mutex& mtx;
			};

		private:

			int recursion_count;
			recursive_mutex mutex;
		};

		class condition_variable_recursive_mutex
		{
		public:
			condition_variable_recursive_mutex(){}

			~condition_variable_recursive_mutex(){}

			void wait(xrecursive_mutex& mtx)
			{
				int extra_lock = mtx.get_recursion_count() - 1;
				for (int i = 0; i < extra_lock; i++)
				{
					mtx.unlock();
				}

				assert(mtx.get_recursion_count() == 1);
				cond.wait(mtx);

				for (int i = 0; i < extra_lock; i++)
				{
					mtx.lock();
				}
			}

			void notify_one()
			{
				cond.notify_one();
			}

			void notify_all()
			{
				cond.notify_all();
			}

		private:
			condition_variable_any cond;
		};
	}
}

#endif //_THREAD_BASE_HH_H
